﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Admin.NET.Application.Entity;
using Admin.NET.Application.Service;
using Furion.FriendlyException;
using MailKit.Search;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Furion.Logging;
using Aop.Api.Domain;
using Org.BouncyCastle.Ocsp;
using MyDemo.Application.RequestRespont;
using MyDemo.Application.Service.Plc;
using Admin.NET.Application.Service.OrderInfo;
using SL.NET.Core;
using Admin.NET.Application.Service.Position.Dto;
using Admin.NET.Application.Service.Warehouse.Dto;
using System.Data;
using WCS.Application.Service.Inventory.DTO;
using Microsoft.IdentityModel.Logging;
using Org.BouncyCastle.Asn1.Ocsp;
using Newtonsoft.Json;
using AngleSharp.Dom;
using WCS.Application.Entity.Warehous;
using WCS.Application.Service.Maintenance;

namespace Admin.NET.Application.Inventory.InventoryService;
/// <summary>
/// 库存管理
/// </summary>
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 11)]
[AllowAnonymous]
public class InventoryService : IDynamicApiController, ITransient
{

    private readonly SqlSugarRepository<InventoryManagementEntity> _inventory;

    private readonly UserManager _userinfo;
    public InventoryService(SqlSugarRepository<InventoryManagementEntity> inventory, UserManager userinfo)
    {
        _userinfo = userinfo;
        _inventory = inventory;
    }

    /// <summary>  
    /// 获取分页库存 🔖  
    /// </summary>  
    /// <param name="Inventoryinput"></param>  
    /// <returns></returns>  
    [ApiDescriptionSettings(Name = "GetInventoryPageList"), HttpPost]
    public async Task<SqlSugarPagedList<InventoryManagementEntity>> GetInventoryPageList(InventoryManagementDto Inventoryinput)
    {
        SerilogHelper.WriteLog($"获取分页库存开始: {JsonConvert.SerializeObject(Inventoryinput)}");

        var list = await _inventory.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(Inventoryinput.MaterialCode), u => u.MaterialCode.Contains(Inventoryinput.MaterialCode.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(Inventoryinput.Batch), u => u.Batch.Contains(Inventoryinput.Batch.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(Inventoryinput.Palcode), u => u.Palcode.Contains(Inventoryinput.Palcode.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(Inventoryinput.Status.ToString()), u => u.Status.Equals(Inventoryinput.Status))
            .OrderBy(u => u.CreateTime, SqlSugar.OrderByType.Desc)
            .ToPagedListAsync(Inventoryinput.Page, Inventoryinput.PageSize);
        SerilogHelper.WriteLog($"获取分页库存结束: {JsonConvert.SerializeObject(list)}");

        return list;
    }

    /// <summary>  
    /// 获取库存 🔖  
    /// </summary>  
    /// <param name="Inventoryinput"></param>  
    /// <returns></returns>  
    [ApiDescriptionSettings(Name = "GetInventoryList"), HttpPost]
    public async Task<List<InventoryManagementEntity>> GetInventoryList(InventoryManagementDto Inventoryinput)
    {
        Expression<Func<InventoryManagementEntity, bool>> expression = whereExp =>
            (Inventoryinput.MaterialCode.GetIsEmptyOrNull() || whereExp.MaterialCode.Contains(Inventoryinput.MaterialCode.Trim()))
            &&(Inventoryinput.Status.GetIsEmptyOrNull() || whereExp.Status==Inventoryinput.Status)
            && (Inventoryinput.BoxCode.GetIsEmptyOrNull() || whereExp.BoxCode.Contains(Inventoryinput.BoxCode.Trim()))
            && (Inventoryinput.Palcode.GetIsEmptyOrNull() || whereExp.Palcode.Contains(Inventoryinput.Palcode.Trim()))
            && (Inventoryinput.WarehousePositionCode.GetIsEmptyOrNull() || whereExp.WarehousePositionCode.Contains(Inventoryinput.WarehousePositionCode.Trim()));

        //var sql = _inventory.AsQueryable().WhereIF(expression != null, expression).ToSql();
        //Console.WriteLine($"Generated SQL: {sql}");

        var list = await _inventory.AsQueryable()
            .WhereIF(expression != null, expression)
            .OrderBy(u => u.CreateTime, SqlSugar.OrderByType.Desc)
            .ToListAsync();
        return list;
    }
    /// <summary>
    /// 库存管理
    /// </summary>
    /// <param name="InventoryManagementDto"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "InsertInventory"), HttpPost]
    public async Task<long> InsertInventory(AddInventoryManagementInput InventoryManagementDto)
    {
        #region 唯一索引
        SerilogHelper.WriteLog($"添加库存管理开始: {JsonConvert.SerializeObject(InventoryManagementDto)}");

        Expression<Func<InventoryManagementEntity, bool>> whereExpression = whereExp =>
                    whereExp.Palcode.Equals(InventoryManagementDto.Palcode) 
                    //&& whereExp.MaterialCode.Equals(InventoryManagementDto.Palcode)
                    ;
        #endregion

        var data = await _inventory.Context.CopyNew().Queryable<InventoryManagementEntity>().Where(whereExpression).ToListAsync();
        if (data.Count > 0)
        {
            throw Oops.Oh("该记录已存在");
        }

        var entity = InventoryManagementDto.Adapt<InventoryManagementEntity>();

        // 填充实体的其他字段  
        entity.CreateUserId = _userinfo.UserId;
        entity.CreateUserName = _userinfo.RealName;
        entity.CreateOrgId = _userinfo.OrgId;
        entity.CreateTime = DateTime.Now;

        var Inventoryid = 0;

        Inventoryid = await _inventory.Context.CopyNew().Insertable<InventoryManagementEntity>(entity).ExecuteCommandAsync();
        SerilogHelper.WriteLog($"添加库存管理结束: {JsonConvert.SerializeObject(Inventoryid)}");

        return Inventoryid;
    }

    /// <summary>
    /// 修改库存管理
    /// </summary>
    /// <param name="entity"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateInventory"), HttpPost]
    public async Task UpdateInventory(UpdateInventoryManagementDtoInput entity)
    {

        SerilogHelper.WriteLog($"修改库存管理开始: {JsonConvert.SerializeObject(entity)}");

        #region 唯一索引  
        Expression<Func<InventoryManagementEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(entity.Id);
        #endregion
        var Inventory = await _inventory.GetFirstAsync(u => u.Id == entity.Id);

        try
        {
            if (Inventory != null)
            {


                // 更新用户信息  
                Inventory.UpdateUserId = _userinfo.UserId;
                Inventory.UpdateTime = DateTime.Now;
                Inventory.UpdateUserName = entity.UpdateUserName;
                Inventory.Reference = entity.Reference;
                Inventory.Status = entity.Status;
                Inventory.Available = entity.Available;
                Inventory.Batch = entity.Batch;


            }
            else
            {
                SerilogHelper.WriteLog("UpdateInventory查询不到核对状态" + ErrorCodeEnum.D1002);
                throw Oops.Oh(ErrorCodeEnum.D1002);
            }
        }
        catch (Exception error)
        {
            SerilogHelper.WriteLog("UpdateInventory失败");
            throw Oops.Oh("修改库存管理出现错误：" + error.Message + "");
        }
        var invtirt = Inventory.Adapt<InventoryManagementEntity>();
        await _inventory.AsUpdateable(invtirt).IgnoreColumns(true).ExecuteCommandAsync();
        SerilogHelper.WriteLog($"修改库存管理结束: {JsonConvert.SerializeObject(invtirt)}");

    }
    /// <summary>
    /// 批量删除
    /// </summary>
    /// <param name="inputList"></param>
    /// <returns></returns>
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "BatchDeleteInventory"), HttpDelete]
    [DisplayName("批量删除")]
    public virtual async Task<int> BatchDeleteInventory(List<DeleteInventoryManagementDtoInput> inputList)
    {
        #region "校验"
        foreach (var input in inputList)
        {
            Expression<Func<InventoryManagementEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(input.Id)
                   ;
            var data = await _inventory.GetFirstAsync(whereExpression);
            if (data == null)
            {
                throw Oops.Oh("该记录不存在");
            }

            // *****校验是否有其他表使用该记录*****
        }
        #endregion

        var deleteEntity = inputList.Adapt<List<InventoryManagementEntity>>();
        return await _inventory.AsDeleteable()
            .Where(deleteEntity)
            .ExecuteCommandAsync();
    }
    /// <summary>
    /// 删除库存管理🔖
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "DeleteInventory"), HttpPost]
    [DisplayName("删除库存管理")]
    public async Task DeleteInventory(DeleteInventoryManagementDtoInput input)
    {
        SerilogHelper.WriteLog($"删除库存管理开始: {JsonConvert.SerializeObject(input)}");

        #region "校验唯一索引"
        Expression<Func<InventoryManagementEntity, bool>> whereExpression = whereExp =>
                    whereExp.Id.Equals(input.Id);
        #endregion    
        var entity = await _inventory.GetFirstAsync(whereExpression) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        if (entity.Status != InventoryStatus.正常)
        {
            throw Oops.Oh("库存管理状态不允许删除");

        }
        //添加逻辑当前物料是否有在执行的 带出来提示
        else
        {
            await _inventory.DeleteAsync(entity); // 假删除
            //await _rep.DeleteAsync(entity); // 真删除
        }
        SerilogHelper.WriteLog($"删除库存管理结束: {""}");

    }

    /// <summary>
    /// 修改库存管理 解冻冻结
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "UpdateInventoryStatus"), HttpPost]
    [DisplayName("修改库存管理 解冻冻结")]
    public async Task UpdateInventoryStatus(List<DeleteInventoryManagementDtoInput> input)
    {
        SerilogHelper.WriteLog("Inventory","Update",$"解冻冻结库存管理开始: {JsonConvert.SerializeObject(input)}");

        foreach (var item in input)
        {
            #region "校验唯一索引"
            Expression<Func<InventoryManagementEntity, bool>> whereExpression = whereExp =>
                        whereExp.Id.Equals(item.Id);
            #endregion    
            var entity = await _inventory.GetFirstAsync(whereExpression) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
            if (entity.Status != InventoryStatus.正常)
            {
                entity.Status = InventoryStatus.正常;
                await _inventory.UpdateAsync(entity);

            }
            else
            {
                entity.Status = InventoryStatus.冻结;
                await _inventory.UpdateAsync(entity);
            }
        }
        SerilogHelper.WriteLog("Inventory","Update",$"解冻冻结库存管理结束: {JsonConvert.SerializeObject(input.Count)}条数据跟新");


    }
    /// <summary>
    /// 下载模版
    /// </summary>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("下载模版")]
    public virtual async Task<IActionResult> DownloadInventoryTemplate()
    {
        return await Task.Run(() =>
        {
            #region "校验"
            string fileName = "InventoryTemplate.xlsx";
            string filePath = $"{AppDomain.CurrentDomain.BaseDirectory}/Template/{fileName}";
            if (!File.Exists(filePath))
            {
                throw Oops.Oh(10002, "找不到该模板：" + filePath);
            }
            #endregion

            var path = Path.Combine(filePath);
            return new FileStreamResult(new FileStream(path, FileMode.Open), System.Net.Mime.MediaTypeNames.Application.Octet)
            {
                FileDownloadName = fileName
            };
        });
    }

    /// <summary>
    /// 导出库存管理
    /// </summary>·
    [UnitOfWork]
    [DisplayName("Inventory")]
    [ApiDescriptionSettings(Name = "InventoryExport"), HttpPost]
    public virtual async Task<IActionResult> InventoryExport(ExportInventoryManagementDtoInput Inventoryinput)
    {

        SerilogHelper.WriteLog($"导出库存管理开始: {Inventoryinput}");

        Expression<Func<InventoryManagementEntity, bool>> expression = whereExp =>
       (Inventoryinput.MaterialCode.GetIsEmptyOrNull() || whereExp.MaterialCode.Contains(Inventoryinput.MaterialCode.Trim()))
     && (Inventoryinput.Status.GetIsEmptyOrNull() || whereExp.Status.Equals(Inventoryinput.Status))
    && (Inventoryinput.BoxCode.GetIsEmptyOrNull() || whereExp.BoxCode.Contains(Inventoryinput.BoxCode.Trim()));


        var list = await _inventory.AsQueryable()
           .WhereIF(expression != null, expression).OrderBuilder(Inventoryinput)
           .ToListAsync();

        string path = AppDomain.CurrentDomain.BaseDirectory + "Export";
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
        IExcelExporter excelExporter = new ExcelExporter();


        var res = await excelExporter.ExportAsByteArray(list);
        return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = $"InventoryExport_{DateTime.Now.ToString("yyyyMMddHHmmss")}_{new Random().Next(10000000, 99999999)}.xlsx" };
    }


    private WStatusEnum ParseStatusEnum(string value)
    {
        if (int.TryParse(value, out int numericValue))
        {
            // 如果是数字，直接转换为枚举
            return (WStatusEnum)numericValue;
        }
        else if (value == "启用" || value == "有货" || value == "是")
        {
            return WStatusEnum.Enable;
        }
        else if (value == "停用" || value == "无货" || value == "否")
        {
            return WStatusEnum.Disable;
        }
        else
        {
            throw new Exception($"无法解析的状态值: {value}");
        }
    }
    private InventoryStatus ParseInventoryStatus(string value)
    {
        if (int.TryParse(value, out int numericValue))
        {
            // 如果是数字，直接转换为枚举
            return (InventoryStatus)numericValue;
        }
        else if (value == "正常")
        {
            return InventoryStatus.正常;
        }
        else if (value == "冻结")
        {
            return InventoryStatus.冻结;
        }
        else
        {
            throw new Exception($"无法解析的状态值: {value}");
        }
    }
    /// <summary>
    /// 导入
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    [UnitOfWork]
    [DisplayName("导入")]
    [ApiDescriptionSettings(Name = "ImportInventory"), HttpPost]
    public virtual async Task<List<ImportInventoryOutput>> ImportInventory([Required] IFormFile file)
    {

        if (file != null)
        {
            var fileDir = AppDomain.CurrentDomain.BaseDirectory + @"ImportFile";
            if (!Directory.Exists(fileDir))
            {
                Directory.CreateDirectory(fileDir);
            }
            //文件名称
            string fileName = file.FileName;
            //文件类型
            string fileType = file.FileName.Substring(fileName.LastIndexOf("."));
            //上传的文件的路径
            string filePath = fileDir + $@"/{fileName}";
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
            {
                file.CopyTo(fs);
            }

            if (fileType == ".xlsx" || fileType == ".xls")
            {
                ExcelHelper eh = new ExcelHelper(filePath);
                DataTable dt = eh.ExcelToDataTable("", true);
                eh.Dispose();
                if (dt == null || dt.Rows.Count == 0)
                {
                    throw Oops.Oh(10002, "文件为空！");
                }

                #region "校验模板字段"
                if (!dt.Columns.Contains("物料编码") || !dt.Columns.Contains("物料名称") || !dt.Columns.Contains("批次") || !dt.Columns.Contains("参考号") || !dt.Columns.Contains("收货日期") || !dt.Columns.Contains("箱条码") || !dt.Columns.Contains("子托盘") || !dt.Columns.Contains("母托盘") || !dt.Columns.Contains("库存状态"))
                {
                    throw Oops.Oh("文件模板错误！请重新下载模板");
                }
                #endregion

                List<ImportInventoryOutput> listLoad = new List<ImportInventoryOutput>();
                int i = 0;
                foreach (DataRow row in dt.Rows)
                {
                    i++;
                    ////校验关联信息是否正确仓库代码
                    //var warehouseCodeList = await GetInventoryList(new WarehouseInput { Code = row["仓库代码"].GetCString(), Isenable = (int)WStatusEnum.Enable });
                    //if (warehouseCodeList.Count() < 1)
                    //{
                    //    throw Oops.Oh($"文件内容填写出错！第{i}行仓库代码列没有{row["仓库代码"].GetCString()}请重新填写");

                    //}

                    ImportInventoryOutput importPosition = new ImportInventoryOutput
                    {
                        #region "字段"
                        MaterialCode = row["物料编码"].GetCString(),
                        MaterialName = row["物料名称"].GetCString(),
                        Batch = row["批次"].GetCString(),
                        Reference = row["参考号"].GetCString(),
                        DateofReceipt = row["收货日期"].GetCDate(),
                        BoxCode = row["箱条码"].GetCString(),
                        Subtray = row["子托盘"].GetCString(),
                        Palcode = row["母托盘"].GetCString(),
                        Number = row["数量"].GetCInt(),
                        WarehousePositionCode = row["当前库位"].GetCString(),
                        WarehousCode = row["当前仓库编码"].GetCString(),
                        Status = ParseInventoryStatus(row["库存状态"].GetCString()),
                        Available = ParseStatusEnum(row["是否有货"].GetCString())
                        #endregion
                    };
                    #region "校验必填项"

                    #endregion
                    //用唯一索引查询非重复
                    Expression<Func<InventoryManagementEntity, bool>> whereExpression = whereExp =>
                        whereExp.BoxCode.Equals(importPosition.BoxCode);
                    var data = await _inventory.GetFirstAsync(whereExpression);
                    if (data == null)
                    {
                        #region "自定义校验"

                        data = importPosition.Adapt(importPosition);
                        data.CreateOrgId = _userinfo.OrgId;
                        data.CreateUserName = _userinfo.RealName;
                        data.CreateUserId = _userinfo.UserId;
                        data.CreateTime = DateTime.Now; ;
                        #endregion

                        var rtAdd = await _inventory.AsInsertable(data).ExecuteCommandAsync();
                        if (rtAdd != 1)
                        {
                            importPosition.ResultCode = 10004;
                            importPosition.Message = "插入失败";
                        }
                    }
                    else
                    {
                        #region "自定义校验"
                        data.UpdateUserId = _userinfo.UserId;
                        data.UpdateTime = DateTime.Now;
                        data.UpdateUserName = _userinfo.RealName;

                        #endregion
                        data.UpdateUserId = _userinfo.UserId;
                        data.UpdateUserName = _userinfo.RealName;
                        data.UpdateTime = DateTime.Now;

                        data.Available = importPosition.Available;
                        importPosition.Id = data.Id;

                        //不能用Adapt替换因为importPosition中没主键
                        //data = data.Adapt(importPosition, config);
                        data = importPosition.Adapt(data);


                        var rtUpdate = await _inventory.AsUpdateable(data).ExecuteCommandAsync();
                        if (rtUpdate != 1)
                        {
                            importPosition.ResultCode = 10004;
                            importPosition.Message = "更新失败";
                        }
                    }

                    if (importPosition.ResultCode != 200)
                        listLoad.Add(importPosition);
                }

                // 返回导入失败数据
                if (listLoad.Count > 0)
                {
                    return listLoad;
                }
            }
            else
            {
                throw Oops.Oh(10002, "文件内容为空！");
            }
        }
        else
        {
            throw Oops.Oh(10002, "请选择文件！");
        }
        return null;
    }

    //internal async Task BeginTransactionAsync(Func<Task> action)
    //{
    //    try
    //    {
    //        // 开启事务
    //        _inventory.Ado.BeginTran();

    //        // 执行操作
    //        await action();

    //        // 提交事务
    //        _inventory.Ado.CommitTran();
    //    }
    //    catch (Exception ex)
    //    {
    //        // 回滚事务
    //        _inventory.Ado.RollbackTran();
    //        throw new Exception("事务操作失败：" + ex.Message, ex);
    //    }
    //}
}
